#ifndef STATIC_QUEUE_ITERATOR_HPP
#define STATIC_QUEUE_ITERATOR_HPP

#include <std/cstddef>

namespace impl
{

template <class T, size_t MaxSize>
class StaticQueueIterator
{
	public:
		explicit StaticQueueIterator(T* array, size_t index);
		T& operator*() const;
		T* operator->() const;
		StaticQueueIterator& operator++();
		StaticQueueIterator operator++(int);
		StaticQueueIterator& operator--();
		StaticQueueIterator operator--(int);
		bool operator==(const StaticQueueIterator& other) const;
		bool operator!=(const StaticQueueIterator& other) const;

	private:
		T* _array; ///< The iterated buffer.
		size_t _index; ///< The index of the pointed element.
};
}

namespace impl
{

template <class T, size_t MaxSize>
StaticQueueIterator<T, MaxSize>::StaticQueueIterator(T* array, size_t index):
	_array{array},
	_index{index}
{
}

template <class T, size_t MaxSize>
T&  StaticQueueIterator<T, MaxSize>::operator*() const
{
	return _array[_index];
}

template <class T, size_t MaxSize>
T*  StaticQueueIterator<T, MaxSize>::operator->() const
{
	return &operator*(*this);
}

template <class T, size_t MaxSize>
StaticQueueIterator<T, MaxSize>& StaticQueueIterator<T, MaxSize>::operator++()
{
	_index = (_index + 1) % MaxSize;
	return *this;
}

template <class T, size_t MaxSize>
StaticQueueIterator<T, MaxSize> StaticQueueIterator<T, MaxSize>::operator++(int)
{
	StaticQueueIterator tmp{*this};
	operator++();
	return tmp;
}

template <class T, size_t MaxSize>
bool StaticQueueIterator<T, MaxSize>::operator==(const StaticQueueIterator<T, MaxSize>& other) const
{
	return _array == other._array and _index == other._index;
}

template <class T, size_t MaxSize>
bool StaticQueueIterator<T, MaxSize>::operator!=(const StaticQueueIterator<T, MaxSize>& other) const
{
	return not (*this == other);
}

}

#endif
